<template>
    <div class="org-tree">
        <el-tree
            ref="tree"
            :key="treeKey"
            v-if="dataTree.length > 0"
            node-key="id"
            :default-expand-all="true"
            :data="dataTree"
            :draggable="idCanDrag"
            :props="defaultProps"
            :expand-on-click-node="clickNodeExpand"
            :filter-node-method="filterNode"
            :show-checkbox="showCheckbox"
            :allow-drop="allowDrop"
            @node-drop="handleDrop"
            @check-change="handleCheckChange">
            <span class="custom-tree-node" slot-scope="{ node, data }">
                <template v-if="canEdit && data.name !== ''">
                    <span class="tree-item-name" :title="data.name" :class="{activeNode: activeNode === data.id}"
                          @click="handleNodeClick(node, data)">
                        <img v-if="data.icon" :src="$staticUrl + data.icon" class="node-img">
                        <span>{{ data.name }}</span>
                    </span>
                    <el-popover
                        placement="right-start"
                        width="100"
                        popper-class="tree-item-btn-popper"
                        trigger="hover">
                        <div class="btn" v-if="node.level < maxLevel + 1 && !noRegional && node.level !== 1" @click="addItem(data, 'onlyName', node.level)">添加子级</div>
                        <div class="btn" v-if="node.level !== 1 && canUpdate" @click="editTreeNode(node, data)">编辑</div>
                        <div class="btn" v-if="node.level !== 1 && canDelete" @click="deleteItem(node, data)">删除</div>
                        <span class="tree-item-btn-box" slot="reference" v-if="(node.level < maxLevel + 1 && !noRegional && node.level !== 1) || (node.level !== 1 && canUpdate) || (node.level !== 1 && canDelete)">
                            <i class="el-icon-more more-btn"></i>
                        </span>
                    </el-popover>
                </template>
                <span v-else class="tree-item-name" :title="data.name" :class="{activeNode: activeNode === data.id}"
                      @click="handleNodeClick(node, data)">{{ data.name }}</span>
            </span>
        </el-tree>
        <ask-empty-text v-else/>
    </div>
</template>

<script lang="ts">
import { Component, Prop, Watch, Vue } from "vue-property-decorator";

@Component
export default class OrgTree extends Vue {
    // 树结构数据
    @Prop({ required: true }) private treeData: any;
    // 当前选中节点
    @Prop({ default: "" }) private value: any;
    // 是否可选择节点
    @Prop({ default: false }) private showCheckbox: boolean | undefined;
    // 是否可编辑/删除
    @Prop({ default: false }) private canEdit: boolean | undefined;
    // 是否可删除
    @Prop({ default: true }) private canDelete: boolean | undefined;
    // 是否可拖动
    @Prop({ default: false }) private canDrag: boolean | undefined;
    // 是否可修改
    @Prop({ default: true }) private canUpdate: boolean | undefined;
    // canDrag 为true时 不允许拖拽的层级，小于和等于这个值得层级都不允许拖动
    @Prop({ default: 1 }) private disabledDragLevel!: number;
    // 点击节点展开
    @Prop({ default: true }) private clickNodeExpand: boolean | undefined;
    // 没有地区选择，只有1级，不能添加
    @Prop({ default: false }) private noRegional: number | undefined;
    // 不要全部
    @Prop({ default: false }) private noAll: boolean | undefined;
    // 过滤内容
    @Prop({ default: "" }) private filterWord: string | undefined;
    // 最大层级
    @Prop({ default: 3 }) private maxLevel!: number;

    get idCanDrag() {
        return this.canDrag && !Object.keys(this.showInput).length;
    }

    @Watch("treeData", { immediate: true })
    changeTree() {
        this.dataTree = this.treeData;
        this.treeKey++;
    }

    @Watch("filterWord")
    changeFilterWord() {
        (this.$refs.tree as any).filter(this.filterWord);
        this.treeKey++;
    }

    @Watch("value")
    changeValue() {
        this.activeNode = this.value;
    }

    created() {
        if (this.treeData.length) {
            this.activeNode = this.treeData[0].id;
        }
    }

    dataTree: any = []

    // 防止双击触发单机
    dblclickTime: any = null;

    // 显示编辑框
    showInput: any = {};
    oldName = "";

    // 当前选中节点
    activeNode = 0;

    // 节点属性
    defaultProps = {
        children: 'children',
        label: 'name'
    }

    treeKey = 0

    // 当前新增节点
    addItemNode = {}

    // 查看列表
    handleNodeClick(node: any, data: any) {
        if (this.clickNodeExpand) return false;
        clearTimeout(this.dblclickTime);
        this.dblclickTime = setTimeout(() => {
            this.activeNode = data.id;
            this.$emit("clickNode", data);
        }, 300);
    }

    // 编辑名称
    editTreeNode(node: any, data: any) {
        this.$emit("handleItem", {
            data,
            nowLevel: node.level - 1
        });
    }

    // 保存输入内容
    saveInput(node: any, data: any) {
        const flag = data.name.match(/^[ ]*$/);
        if (flag && data.id === "AddItem") {
            (this.$refs.tree as any).remove(data.id);
        } else if (this.oldName === "") {
            if (flag) {
                (this.$refs.tree as any).remove(data.id);
            } else {
                this.addDepartment(data);
            }
        } else {
            data.name = !flag ? data.name : this.oldName;
            if (!flag) {
                this.addDepartment(data);
            }
        }
        this.showInput = {};
        this.oldName = "";
    }

    // 关闭输入框
    closeInput() {
        if (!Object.keys(this.showInput).length) return;
        if (this.showInput.id === "AddItem") {
            (this.$refs.tree as any).remove(this.showInput.id);
        } else {
            (this.$refs.tree as any).getNode(this.showInput.id).data.name = this.oldName;
        }
        this.showInput = {};
        this.oldName = "";
    }

    // 添加部门
    addDepartment(data: any, type?: any) {
        const node = (this.$refs.tree as any).getNode(data.id) || this.addItemNode;
        if (!type) {
            this.$emit("addDepartment", {
                id: data.id === "AddItem" ? "" : data.id,
                name: data.name,
                tel: data.tel,
                description: data.description,
                tier: node.level - 1,
                parentId: node.parent.data.id,
                icon: data.icon || undefined,
                color: data.color || undefined
            });
        } else {
            this.$emit("addDepartment", {
                field: data.field,
                id: data.id === "AddItem" ? "" : data.id,
                name: data.name,
                tier: node.level - 1,
                parentId: node.parent.data.id,
                icon: data.icon || undefined,
                color: data.color || undefined
            });
        }
    }

    // 添加子级
    addItem(data: any, onlyName?: any, nowLevel?: any) {
        this.addItemNode = {};
        this.closeInput();
        const child = {
            name: '',
            id: "AddItem",
            children: []
        };
        if (!data) {
            this.dataTree[0].children.push(child);
        } else {
            if (!data.children) {
                this.$set(data, 'children', []);
            }
            data.children.push(child);
        }
        this.$nextTick(() => {
            const node = (this.$refs.tree as any).getNode("AddItem");
            this.addItemNode = {
                ...node,
                parent: node.parent
            };
            (this.$refs.tree as any).remove("AddItem");
            this.$emit("handleItem", {
                data: child,
                onlyName: Boolean(onlyName),
                nowLevel: nowLevel || 0
            });
            this.showInput = {
                nodeAddItem: true,
                id: "AddItem"
            };
        });
    }

    // 删除节点
    deleteItem(node: any, data: any) {
        this.$emit("deleteDepartment", data, (val: any) => {
            if (val) {
                const parent = node.parent;
                const children = parent.data.children || parent.data;
                const index = children.findIndex((d: any) => d.id === data.id);
                children.splice(index, 1);
            }
        });
    }

    // 复选框选中状态切换
    handleCheckChange() {
        this.$emit('getCheckedNodes', (this.$refs.tree as any).getCheckedNodes());
    }

    /**
     * 拖拽成功后
     * @param draggingNode 被拖拽节点
     * @param dropNode 进入的节点
     * @param dropType 拖拽方式（inner，before，after）
     */
    async handleDrop(draggingNode: any, dropNode: any, dropType: string) {
        this.$emit("addDepartment", {
            id: draggingNode.data.id,
            name: draggingNode.data.name,
            tier: ["before", "after"].includes(dropType) ? dropNode.level - 1 : dropNode.level, // 是inner的话因为从0开始，所以不用-1
            parentId: ["before", "after"].includes(dropType) ? dropNode.data.parentId || 0 : dropNode.data.id
        });
    }

    /**
     * 是否允许拖拽成功
     * @param draggingNode 被拖拽节点
     * @param dropNode 进入的节点
     * @param type 放置方式（prev，inner，next），目标节点前中后
     */
    allowDrop(draggingNode: any, dropNode: any, type: any) {
        if (!this.idCanDrag) { return false; }
        const getLastPlies = (sourceChild: any) => {
            let _lastPlies = 1;
            const transferChild = (child: any, pPlies: any) => {
                if (child.childNodes && child.childNodes.length > 0) {
                    if (_lastPlies === pPlies) {
                        _lastPlies += 1;
                    }
                    child.childNodes.forEach((cur: any) => {
                        transferChild(cur, _lastPlies);
                    });
                }
            };
            transferChild(sourceChild, _lastPlies);
            return _lastPlies;
        };
        const lastPlies = getLastPlies(draggingNode);
        const dropLevel = lastPlies + dropNode.level;
        const dropEndLevel = type === "inner" ? this.maxLevel + 1 : this.maxLevel + 2;
        if (dropLevel > dropEndLevel || dropNode.level >= dropEndLevel || dropNode.level <= this.disabledDragLevel) { return false; }
        return true;
        // if (dropNode.data.id === "ALL_DEPARTMENT" && type !== 'inner') return false; // 不能和全部同级
        // if (this.noRegional && dropNode.data.id !== "ALL_DEPARTMENT" && type === 'inner') return false; // 只能有一级，不能放入到除全部以外位置
        // const nodeChild = this.getNodeChildLevel(draggingNode);
        // if (type === 'inner') {
        //     if (dropNode.level === 4) return false; // 最多三级
        //     if (dropNode.level === 3 && !draggingNode.isLeaf) return false; // 二级下进无子级的
        //     if (dropNode.level === 2 && nodeChild === 2) return false; // 一级下进只有一层子级的
        // }
        // if (dropNode.level === 4 && !draggingNode.isLeaf) return false; // 三级同级放无子级的
        // if (dropNode.level === 3 && nodeChild === 2) return false; // 二级同级只有一层子级的
        // return true;
    }

    // 获取节点子级层数
    // getNodeChildLevel(child: any) {
    //     let num = 0;
    //     if (!child.isLeaf) {
    //         num = 1;
    //         for (const i in child.childNodes) {
    //             if (!child.childNodes[i].isLeaf) {
    //                 num = 2;
    //                 break;
    //             }
    //         }
    //     }
    //     return num;
    // }

    // 获取节点
    getNode(id: any) {
        return (this.$refs.tree as any).getNode(id);
    }

    // 过滤节点
    filterNode(value: any, data: any) {
        if (!value || (data.id === "ALL_DEPARTMENT")) return true;
        return data.name.indexOf(value) !== -1;
    }
}
</script>
<style lang="scss" scoped>
.org-tree {
    .custom-tree-node {
        width: calc(100% - 24px);
        display: flex;
        justify-content: space-between;
        align-items: center;
        font-size: 0.14rem;
        .node-img {
            display: inline-block;
            width: 20px;
            height: 20px;
            object-fit: contain;
            margin-right: 4px;
        }
        .edit-tree-name {
            width: calc(100% - 3px);
            ::v-deep {
                .el-input__inner {
                    height: 0.2rem;
                    line-height: 0.2rem;
                    border: 1px solid #000;
                }
            }
        }

        .el-icon-check, .el-icon-close {
            font-size: 0.18rem;
            color: #333;
            margin-left: 4px;
        }

        .tree-item-name {
            display: inline-flex;
            align-items: center;
            width: calc(100% - 66px);
            line-height: 0.26rem;
            span {
                display: inline-block;
                width: 100%;
                @include textEllipsis();
            }
        }

        .activeNode {
            color: #de2728;
        }

        .tree-item-btn-box {
            display: none;

            i {
                font-size: 14px;
                color: #bbb;
                margin-left: 4px;
                padding: 4px;
            }

            .more-btn {
                transform: rotate(90deg);
                cursor: pointer;
            }
        }
        &:hover {
            .tree-item-btn-box {
                display: inline-block;
            }
        }
    }
}
.tree-item-btn-popper {
    padding: 0;
    .btn {
        cursor: pointer;
        font-size: 14px;
        line-height: 28px;
        color: #37383a;
        &:hover {
            color: #de2728;
        }
    }
}
</style>
